package com.opages.mvc.adapter.common.condition;

import com.opages.mvc.adapter.common.condition.annotation.ConditionalOnProperty;
import com.opages.mvc.adapter.common.condition.core.ConditionOutcome;
import org.springframework.beans.factory.config.BeanExpressionContext;
import org.springframework.beans.factory.config.BeanExpressionResolver;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.context.expression.StandardBeanExpressionResolver;
import org.springframework.core.type.AnnotatedTypeMetadata;

/**
 * @author daizhong.liu
 * @create 2020-06-15 17:37
 **/
public class OnPropertyCondition extends AnnotationCondition {
    @Override
    public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {
        String expression = (String)getVal("name",metadata);
        String defVal = (String)getVal("havingValue",metadata);
        if(defVal == null || "".equals(defVal)) {
            return ConditionOutcome.noMatch();
        }
        expression = wrapIfNecessary(expression);
        expression = context.getEnvironment().resolvePlaceholders(expression);
        ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
        if (beanFactory != null) {
            boolean result = evaluateExpression(beanFactory, expression,defVal);
            return new ConditionOutcome(result);
        }
        return ConditionOutcome.noMatch();
    }

    private Boolean evaluateExpression(ConfigurableListableBeanFactory beanFactory, String expression, String defVal) {
        BeanExpressionResolver resolver = beanFactory.getBeanExpressionResolver();
        if (resolver == null) {
            resolver = new StandardBeanExpressionResolver();
        }
        BeanExpressionContext expressionContext = new BeanExpressionContext(beanFactory, null);
        Object result = resolver.evaluate(expression, expressionContext);
        return defVal.equals(result);
    }

    private String wrapIfNecessary(String expression) {
        if (!expression.startsWith("${")) {
            return "${" + expression + "}";
        }
        return expression;
    }

    public Object getVal(String annotationName, AnnotatedTypeMetadata metadata) {
        return metadata.getAnnotationAttributes(ConditionalOnProperty.class.getName()).get(annotationName);
    }
}
